package com.ksd.quartz.http;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import java.util.Map;

public class DRMHttpClient {
	private static final Logger logger = LoggerFactory.getLogger(DRMHttpClient.class);
	// 2. 超时配置（抽为常量，方便统一维护，单位：毫秒）
	private static final int SOCKET_TIMEOUT = 15000;    // 读取响应超时：15秒（根据业务调整）
	private static final int CONNECT_TIMEOUT = 8000;    // 建立连接超时：8秒
	private static final int CONN_REQUEST_TIMEOUT = 5000;// 从连接池获取连接超时：5秒

	private static SSLConnectionSocketFactory createSslSocketFactory() {
		try {
			// 信任所有证书（仅用于测试/内部服务，生产环境建议配置真实证书）
			SSLContext sslContext = SSLContexts.custom()
					.loadTrustMaterial(null, (chain, authType) -> true) // 信任所有证书
					.build();

			// 创建SSL连接工厂（禁用主机名验证，仅用于内部服务）
			return new SSLConnectionSocketFactory(
					sslContext,
					NoopHostnameVerifier.INSTANCE
			);
		} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
			logger.error("创建HTTPS SSL连接工厂失败", e);
			throw new RuntimeException("HTTPS SSL初始化异常", e);
		}
	}

	public static String udrmHttpDoPost(String url, String requestData) {
		// 4.1 初始化资源（使用Closeablexxx接口，确保可关闭）
		BasicHttpClientConnectionManager connManager = null;
		CloseableHttpClient httpClient = null;
		HttpResponse httpResponse = null;
		HttpEntity httpEntity = null;

		try {
			// 4.2 构建连接管理器（HTTP + HTTPS）
			connManager = new BasicHttpClientConnectionManager(
					RegistryBuilder.<ConnectionSocketFactory>create()
							.register("http", PlainConnectionSocketFactory.getSocketFactory())
							.register("https", createSslSocketFactory()) // 复用HTTPS配置
							.build()
			);

			// 4.3 构建HttpClient（使用CloseableHttpClient，支持手动关闭）
			httpClient = HttpClientBuilder.create()
					.setConnectionManager(connManager)
					.build();

			// 4.4 构建POST请求 + 超时配置（核心：绑定超时参数）
			HttpPost httpPost = new HttpPost(url);
			RequestConfig requestConfig = RequestConfig.custom()
					.setSocketTimeout(SOCKET_TIMEOUT)       // 读取超时（解决Read timed out）
					.setConnectTimeout(CONNECT_TIMEOUT)     // 连接超时
					.setConnectionRequestTimeout(CONN_REQUEST_TIMEOUT) // 连接池超时
					.build();
			httpPost.setConfig(requestConfig);

			// 4.5 设置请求头 + 请求体（避免中文乱码）
			httpPost.addHeader("Content-Type", "application/json; charset=utf-8");
			httpPost.addHeader("Cache-Control", "no-cache");
			if (requestData != null && !requestData.trim().isEmpty()) {
				StringEntity postEntity = new StringEntity(requestData, "UTF-8");
				postEntity.setContentEncoding("UTF-8"); // 明确编码，防止乱码
				httpPost.setEntity(postEntity);
			}

			// 4.6 打印请求日志（便于排查问题）
			logger.info("发送HTTP POST请求 | URL: {}, 请求体: {}", url, requestData);

			// 4.7 执行请求（核心步骤）
			httpResponse = httpClient.execute(httpPost);

			// 4.8 处理响应（先判断响应码，再读响应体）
			int statusCode = httpResponse.getStatusLine().getStatusCode();
			if (statusCode < 200 || statusCode >= 300) {
				logger.error("HTTP请求响应码异常 | URL: {}, 响应码: {}", url, statusCode);
				return null; // 非2xx响应，返回null或自定义错误标识
			}

			// 4.9 读取响应体（必须关闭Entity，避免资源泄漏）
			httpEntity = httpResponse.getEntity();
			String responseStr = EntityUtils.toString(httpEntity, "UTF-8");
			logger.info("HTTP请求成功 | URL: {}, 响应体: {}", url, responseStr);
			return responseStr;

		} catch (java.net.SocketTimeoutException e) {
			// 5. 精准捕获「读取超时」异常（原代码未区分，此处单独处理）
			logger.error("HTTP请求读取超时 | URL: {}, 请求体: {}, 超时时间: {}ms",
					url, requestData, SOCKET_TIMEOUT, e);
			return "HTTP_READ_TIMEOUT"; // 返回明确的超时标识，便于上游处理

		} catch (java.net.ConnectException e) {
			// 6. 精准捕获「连接超时」异常（与读取超时区分）
			logger.error("HTTP请求连接超时 | URL: {}, 无法建立连接", url, e);
			return "HTTP_CONNECT_TIMEOUT";

		} catch (ClientProtocolException e) {
			// 7. 捕获HTTP协议异常（如请求方法错误、协议版本不兼容）
			logger.error("HTTP协议异常 | URL: {}, 请求体: {}", url, requestData, e);
			return null;

		} catch (IOException e) {
			// 8. 捕获IO异常（如网络中断、响应流读取失败）
			logger.error("HTTP请求IO异常 | URL: {}, 请求体: {}", url, requestData, e);
			return null;

		} finally {
			// 9. 强制释放资源（核心：避免连接泄漏、流泄漏）
			try {
				// 9.1 关闭响应体（EntityUtils.consume会自动关闭流）
				if (httpEntity != null) {
					EntityUtils.consume(httpEntity);
				}
				// 9.2 关闭HttpClient（释放连接管理器资源）
				if (httpClient != null) {
					httpClient.close();
				}
				// 9.3 关闭连接管理器（防止资源占用）
				if (connManager != null) {
					connManager.shutdown();
				}
			} catch (IOException e) {
				logger.warn("HTTP资源释放失败", e); // 警告级别，不影响主流程
			}
		}
	}


	public static String udrmHttpDoPostOutTime(String url, String requestData) throws Exception {
		BasicHttpClientConnectionManager connManager = null;
			connManager = new BasicHttpClientConnectionManager(
					RegistryBuilder.<ConnectionSocketFactory>create()
							.register("http", PlainConnectionSocketFactory.getSocketFactory())
							.register("https", new SSLConnectionSocketFactory(
									SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build(),
									NoopHostnameVerifier.INSTANCE))
							.build(),
					null,
					null,
					null
			);

		HttpClient httpClient = HttpClientBuilder.create()
				.setConnectionManager(connManager)
				.build();
		HttpPost httpPost = new HttpPost(url);

		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(10000).build();
		httpPost.setConfig(requestConfig);

		httpPost.addHeader("Content-Type", "application/json; charset=utf-8");
		httpPost.addHeader("Cache-Control", "no-cache");
		StringEntity postEntity = new StringEntity(requestData, "UTF-8");
		httpPost.setEntity(postEntity);

		HttpResponse httpResponse = null;
			httpResponse = httpClient.execute(httpPost);

		HttpEntity httpEntity = httpResponse.getEntity();
			return  EntityUtils.toString(httpEntity, "UTF-8");

	}

	public static void udrmHttpDoPostNoResponse(String url, String requestData) {
		BasicHttpClientConnectionManager connManager = null;
		try {
			connManager = new BasicHttpClientConnectionManager(
					RegistryBuilder.<ConnectionSocketFactory>create()
							.register("http", PlainConnectionSocketFactory.getSocketFactory())
							.register("https", new SSLConnectionSocketFactory(
									SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build(),
									NoopHostnameVerifier.INSTANCE))
							.build(),
					null,
					null,
					null
			);

			HttpClient httpClient = HttpClientBuilder.create()
					.setConnectionManager(connManager)
					.build();
			HttpPost httpPost = new HttpPost(url);

			RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(5000).setConnectTimeout(5000).build();
			httpPost.setConfig(requestConfig);

			httpPost.addHeader("Content-Type", "application/json; charset=utf-8");
			httpPost.addHeader("Cache-Control", "no-cache");
			StringEntity postEntity = new StringEntity(requestData, "UTF-8");
			httpPost.setEntity(postEntity);
			HttpResponse httpResponse = null;
			httpResponse = httpClient.execute(httpPost);

		} catch (Exception e) {

		}

	}


	public static DRMHttpResponse udrmHttpDoPost(String url, String requestData, Map<String, String> extHeader) {
		BasicHttpClientConnectionManager connManager = null;
		try {
			connManager = new BasicHttpClientConnectionManager(
					RegistryBuilder.<ConnectionSocketFactory>create()
							.register("http", PlainConnectionSocketFactory.getSocketFactory())
							.register("https", new SSLConnectionSocketFactory(
									SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build(),
									NoopHostnameVerifier.INSTANCE))
							.build(),
					null,
					null,
					null
			);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		HttpClient httpClient = HttpClientBuilder.create()
				.setConnectionManager(connManager)
				.build();
		HttpPost httpPost = new HttpPost(url);

		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(10000).build();
		httpPost.setConfig(requestConfig);
		httpPost.addHeader("Content-Type", "application/json");

		Iterator<Map.Entry<String, String>> iter = extHeader.entrySet().iterator();
		while(iter.hasNext()) {
			Map.Entry<String, String> entry = iter.next();
			httpPost.addHeader(entry.getKey(), entry.getValue());
		}

		StringEntity postEntity = new StringEntity(requestData, "UTF-8");
		httpPost.setEntity(postEntity);

		HttpResponse httpResponse = null;
		try {
			httpResponse = httpClient.execute(httpPost);
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		DRMHttpResponse drmHttpResponse = new DRMHttpResponse();
		HttpEntity httpEntity = httpResponse.getEntity();
		try {
			int responseStatusCode = httpResponse.getStatusLine().getStatusCode();
			logger.info("udrmHttpDoPost response status code : " + responseStatusCode);  //401

			drmHttpResponse.setResponseCode(responseStatusCode);
			drmHttpResponse.setResponseBody(EntityUtils.toString(httpEntity, "UTF-8"));

//			logger.info("udrmHttpDoPost response data :"+drmHttpResponse.toString());
			return  drmHttpResponse;
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	public static DRMHttpResponse udrmHttpDoPost2(String url, String requestData, Map<String, String> extHeader) throws IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
		BasicHttpClientConnectionManager connManager = null;

		logger.info("发送请求地址:"+url);
		connManager = new BasicHttpClientConnectionManager(
				RegistryBuilder.<ConnectionSocketFactory>create()
						.register("http", PlainConnectionSocketFactory.getSocketFactory())
						.register("https", new SSLConnectionSocketFactory(
								SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build(),
								NoopHostnameVerifier.INSTANCE))
						.build(),
				null,
				null,
				null
		);

		HttpClient httpClient = HttpClientBuilder.create()
				.setConnectionManager(connManager)
				.build();
		HttpPost httpPost = new HttpPost(url);

		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(3000).setConnectTimeout(3000).build();
		httpPost.setConfig(requestConfig);
		httpPost.addHeader("Content-Type", "application/json");

		Iterator<Map.Entry<String, String>> iter = extHeader.entrySet().iterator();
		while(iter.hasNext()) {
			Map.Entry<String, String> entry = iter.next();
			httpPost.addHeader(entry.getKey(), entry.getValue());
		}

		StringEntity postEntity = new StringEntity(requestData, "UTF-8");
		httpPost.setEntity(postEntity);

		HttpResponse httpResponse = null;

		httpResponse = httpClient.execute(httpPost);

		DRMHttpResponse drmHttpResponse = new DRMHttpResponse();
		HttpEntity httpEntity = httpResponse.getEntity();

		int responseStatusCode = httpResponse.getStatusLine().getStatusCode();
		logger.info("udrmHttpDoPost response status code : " + responseStatusCode);

		drmHttpResponse.setResponseCode(responseStatusCode);
		drmHttpResponse.setResponseBody(EntityUtils.toString(httpEntity, "UTF-8"));

		logger.info("udrmHttpDoPost response data :"+drmHttpResponse.toString());
		return  drmHttpResponse;
	}

	public static String udrmHttpDoGet(String url, String requestData) {
		url = url + "?" + requestData;
		try {
			URL targetUrl = new URL(url);
			HttpURLConnection httpConnect = (HttpURLConnection) targetUrl
					.openConnection();
			httpConnect.setDoOutput(true);
			httpConnect.setDoInput(true);
			httpConnect.setRequestMethod("GET");
			httpConnect.setRequestProperty("Content-Type", "application/json");
			httpConnect.setConnectTimeout(3000);
			httpConnect.connect();
			if (httpConnect.getResponseCode() != 200) {
				return null;
			}
			InputStream in = httpConnect.getInputStream();
			byte[] responseData = read(in);
			String response = new String(responseData,"utf-8");
			in.close();
			httpConnect.disconnect();
			return response;
		} catch (IOException e) {
			logger.error(e.toString());
			return null;
		}
	}

	public static byte[] read(InputStream is) {
		byte[] dateByte = new byte[204800];
		byte[] dataTemp = new byte[8192];
		int len = 0;
		int totalLen = 0;
		try {
			while ((len = is.read(dataTemp)) > 0) {
				System.arraycopy(dataTemp, 0, dateByte, totalLen, len);
				totalLen += len;
			}
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}

		byte[] recvData = new byte[totalLen];
		System.arraycopy(dateByte, 0, recvData, 0, totalLen);
		return recvData;
	}
}